package com.hanson.service;

import com.alibaba.fastjson.JSONObject;
import com.hanson.Const;
import com.hanson.common.bean.*;
import com.hanson.common.exception.BusinessException;
import com.hanson.common.service.RedisService;
import com.hanson.common.util.BusinessUtil;
import com.hanson.common.util.ClientCustomSSL;
import com.hanson.common.util.QrCodeUtil;
import com.hanson.common.util.WeChatUtils;
import com.hanson.entity.*;
import com.hanson.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;

import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

@Service
@Slf4j
public class PayService {
    @Autowired
    private WeiXinConfig weiXinConfig;
    @Autowired
    private OrderService orderService;
    @Autowired
    private ApplyInfoService applyInfoService;
    @Autowired
    private WeiXinNotifyBeanMapper weiXinNotifyBeanMapper;
    @Autowired
    private UserBeanMapper userBeanMapper;
    @Autowired
    private GoodsBeanMapper goodsBeanMapper;
    @Autowired
    private GoodsAttrValueBeanMapper goodsAttrValueBeanMapper;
    @Autowired
    private SeckillGoodsBeanMapper seckillGoodsBeanMapper;
    @Autowired
    private GroupGoodsBeanMapper groupGoodsBeanMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    private ScoreSeqBeanMapper scoreSeqBeanMapper;
    @Autowired
    private AcctbkSeqBeanMapper acctbkSeqBeanMapper;
    @Autowired
    private CouponsBeanMapper couponsBeanMapper;
    @Autowired
    private CouponsSeqBeanMapper couponsSeqBeanMapper;
    @Autowired
    private SpreadInfoBeanMapper spreadInfoBeanMapper;
    @Autowired
    private SpreadMoneyBeanMapper spreadMoneyBeanMapper;
    @Autowired
    private SmsService smsService;
    @Autowired
    private QrCodeUtil qrCodeUtil;

    public Map<String, Object> unifiedOrder(Map<String, Object> map, String orderSeq, ModelMap modelMap, String client) {
        Map<String, Object> resultMap = null;
        try {
            JSONObject paramObj = getOrderInfoByOrderSeq(orderSeq);
            WxPaySendData paySendData = new WxPaySendData();
            //构建微信支付请求参数集合
            String appId = client.equals(Const.CLIENT_MINI) ? weiXinConfig.getMiniappAppId() : weiXinConfig.getAppId();
            String tradeType = client.equals(Const.CLIENT_MINI) ? weiXinConfig.getMiniTradeType() : weiXinConfig.getTradeType();
            paySendData.setAppId(appId);
            paySendData.setAttach(paramObj.getString("attach"));
            paySendData.setBody(paramObj.getString("body"));
            paySendData.setMchId(weiXinConfig.getMchId());
            paySendData.setNonceStr(WeChatUtils.getRandomStr(32));
            paySendData.setNotifyUrl(weiXinConfig.getNotifyUrl());
            paySendData.setDeviceInfo("WEB");
            paySendData.setOutTradeNo(orderSeq);
            paySendData.setTotalFee(paramObj.getString("totalFee"));
            modelMap.put("totalFee", BusinessUtil.getWebAmount(Integer.parseInt(paySendData.getTotalFee())));
            paySendData.setTradeType(tradeType);
            paySendData.setSpBillCreateIp((String) map.get("remoteIp"));
            paySendData.setOpenId((String) map.get("openId"));
            //将参数拼成map,生产签名
            SortedMap<String, Object> params = buildParamMap(paySendData);
            paySendData.setSign(WeChatUtils.createSign(params, weiXinConfig.getPaySignKey()));
            //将请求参数对象转换成xml
            String reqXml = WeChatUtils.sendDataToXml(paySendData);
            log.info("【unifiedOrder reqXml = {} 】", reqXml);
            //发送请求
            byte[] xmlData = reqXml.getBytes("UTF-8");
            URL url = new URL(weiXinConfig.getUniformorderUrl());
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.setRequestProperty("Content_Type", "text/xml");
            urlConnection.setRequestProperty("Content-length",
                    String.valueOf(xmlData.length));
            DataOutputStream outputStream = new DataOutputStream(
                    urlConnection.getOutputStream());
            outputStream.write(xmlData);
            outputStream.flush();
            outputStream.close();
            resultMap = WeChatUtils.parseXml(urlConnection.getInputStream());
            log.info("【unifiedOrder resMap = {} 】", resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(500, "微信支付统一下单异常");
        }
        return resultMap;
    }

    @Transactional(rollbackFor = Exception.class)
    public synchronized void dealNotify(WechatRefundApiResult result) {
        String orderSeq = result.getOut_trade_no();
        String tempOpenId = result.getOpenid();
        UserBean userBean = userBeanMapper.selectByMaOpenId(tempOpenId);
        if (null == userBean) {
            userBean = userBeanMapper.selectByMpOpenId(tempOpenId);
        }
        if (null == userBean) {
            throw new BusinessException(500, "回调找不到用户 openId：" + tempOpenId);
        }
        String attach = result.getAttach();
        String orderType = orderSeq.substring(orderSeq.length() - 1, orderSeq.length());
        int totalFee = Integer.parseInt(result.getTotal_fee());
        int userScore = 0;
        int userMoney = 0;
        Integer userCoupons = 0;
        if ("1".equals(orderType)) {
            List<OrderBean> list = orderService.selectByOrderId(orderSeq);
            if (CollectionUtils.isEmpty(list)) {
                throw new BusinessException(500, "回调找不到订单号：" + orderSeq);
            }
            final int[] totalPayPrice = {0};
            //赠送积分
            int givingScore = 0;
            Set<Integer> merIdSet = new TreeSet<>();
            //分享购买
            Map<Integer, ShareMoneyBean> shareParentMap = new HashMap<>();
            int totalSpreadMoney = 0;
            int totalSpreadChildMoney = 0;
            for (OrderBean c : list) {
                //秒杀、普通订单 直接改成已支付
                if (c.getOrderType() == 1 || c.getOrderType() == 2 || c.getOrderType() == 4) {
                    orderService.updatePayPrice(2, totalFee, c.getId());
                }
                userScore = c.getUserScore();
                userMoney = c.getUserMoney();
                userCoupons = c.getUserCoupons();
                totalPayPrice[0] += c.getTotalPrice();
                //分享人用户ID
                Object parentIdObj = redisService.hget(String.format(Const.SHARE_GOODS_KEY, c.getGoodsId()), c.getOpenId());
                int parentId = null == parentIdObj ? -1 : Integer.parseInt(parentIdObj.toString());
                redisService.hdel(String.format(Const.SHARE_GOODS_KEY, c.getGoodsId()), c.getOpenId());
                //普通订单或积分订单
                if (c.getOrderType() == 1 || c.getOrderType() == 4) {
                    GoodsBean goodsBean = goodsBeanMapper.selectByPrimaryKey(c.getGoodsId());
                    if (null != goodsBean) {
                        if (goodsBean.getScore() != null && goodsBean.getScore() != 0) {
                            givingScore += goodsBean.getScore();
                        }
                        goodsBean.setStock(goodsBean.getStock() - c.getTotalNum());
                        goodsBean.setSales(goodsBean.getSales() + c.getTotalNum());
                        goodsBeanMapper.updateByPrimaryKey(goodsBean);
                        if (goodsBean.getIsBevip() == 1) {//vip商品
                            List<ApplyInfoBean> applyInfoBeanList = applyInfoService.selectByOpenIdAndType(userBean.getOpenId(), 1);
                            if (!CollectionUtils.isEmpty(applyInfoBeanList)) {
                                ApplyInfoBean applyInfoBean = applyInfoBeanList.get(0);
                                applyInfoBean.setStatus(1);
                                applyInfoBean.setRemark("购买商品成为VIP");
                                applyInfoService.updateApplyInfo(applyInfoBean);

                                userBean.setIsVip(1);
                                userBean.setUpdateDate(new Date());
                                userBeanMapper.updateByPrimaryKeySelective(userBean);
                                redisService.del(String.format(Const.USER_REDIS_KEY, userBean.getOpenId()));
                            }
                        }
                        if (goodsBean.getIsBepartner() == 1) {//合伙人商品
                            List<ApplyInfoBean> applyInfoBeanList = applyInfoService.selectByOpenIdAndType(userBean.getOpenId(), 2);
                            if (!CollectionUtils.isEmpty(applyInfoBeanList)) {
                                ApplyInfoBean applyInfoBean = applyInfoBeanList.get(0);
                                applyInfoBean.setStatus(1);
                                applyInfoBean.setRemark("购买商品成为合伙人");
                                applyInfoService.updateApplyInfo(applyInfoBean);

                                String miniUrl = qrCodeUtil.createQrCode(Const.CLIENT_MINI, userBean.getId());
                                String h5Url = qrCodeUtil.createQrCode(Const.CLIENT_H5, userBean.getId());
                                userBean.setSignDate(new Date());
                                userBean.setUserSign(miniUrl + "," + h5Url);
                                userBean.setIsVip(1);
                                userBean.setIsSpread(1);
                                userBean.setUpdateDate(new Date());
                                userBeanMapper.updateByPrimaryKeySelective(userBean);
                                redisService.del(String.format(Const.USER_REDIS_KEY, userBean.getOpenId()));
                            }
                        }
                        merIdSet.add(goodsBean.getMerId());
                        List<GoodsAttrValueBean> goodsAttrValueBeanList = goodsAttrValueBeanMapper.selectByByGoodsIdAndSuk(goodsBean.getId(), c.getGoodsAttr(), 1);
                        if (!CollectionUtils.isEmpty(goodsAttrValueBeanList)) {
                            GoodsAttrValueBean goodsAttrValueBean = goodsAttrValueBeanList.get(0);
                            int spreadMoney = goodsAttrValueBean.getSpreadMoney() == null ? 0 : Integer.parseInt(goodsAttrValueBean.getSpreadMoney());
                            int speadChildMoney = goodsAttrValueBean.getSpreadChildMoney() == null ? 0 : Integer.parseInt(goodsAttrValueBean.getSpreadChildMoney());
                            totalSpreadMoney += spreadMoney;
                            totalSpreadChildMoney += speadChildMoney;
                            if (-1 != parentId) {
                                shareParentMap.put(parentId, new ShareMoneyBean(totalSpreadMoney, totalSpreadChildMoney));
                            }
                        }
                    }
                } else if (c.getOrderType() == 2) {//秒杀订单
                    List<SeckillGoodsBean> seckillGoodsBeanList = seckillGoodsBeanMapper.selectByGoodsId(c.getGoodsId());
                    if (!CollectionUtils.isEmpty(seckillGoodsBeanList)) {
                        SeckillGoodsBean seckillGoodsBean = seckillGoodsBeanList.get(0);
                        seckillGoodsBean.setStock(seckillGoodsBean.getStock() - c.getTotalNum());
                        seckillGoodsBean.setSales(seckillGoodsBean.getSales() + c.getTotalNum());
                        seckillGoodsBean.setUpdateDate(new Date());
                        seckillGoodsBeanMapper.updateByPrimaryKey(seckillGoodsBean);
                        merIdSet.add(0);
                        List<GoodsAttrValueBean> goodsAttrValueBeanList = goodsAttrValueBeanMapper.selectByByGoodsIdAndSuk(seckillGoodsBean.getId(), c.getGoodsAttr(), 3);
                        if (!CollectionUtils.isEmpty(goodsAttrValueBeanList)) {
                            GoodsAttrValueBean goodsAttrValueBean = goodsAttrValueBeanList.get(0);
                            int spreadMoney = goodsAttrValueBean.getSpreadMoney() == null ? 0 : Integer.parseInt(goodsAttrValueBean.getSpreadMoney());
                            int speadChildMoney = goodsAttrValueBean.getSpreadChildMoney() == null ? 0 : Integer.parseInt(goodsAttrValueBean.getSpreadChildMoney());
                            totalSpreadMoney += spreadMoney;
                            totalSpreadChildMoney += speadChildMoney;
                            if (-1 != parentId) {
                                shareParentMap.put(parentId, new ShareMoneyBean(totalSpreadMoney, totalSpreadChildMoney));
                            }
                        }
                    } else {
                        log.error("【秒杀订单 {} 找不到商品】", c.getOrderId());
                    }
                    //拼团订单
                } else if (c.getOrderType() == 3) {
                    List<GroupGoodsBean> groupGoodsBeanList = groupGoodsBeanMapper.selectByGoodsId(c.getGoodsId());
                    if (!CollectionUtils.isEmpty(groupGoodsBeanList)) {
                        GroupGoodsBean groupGoodsBean = groupGoodsBeanList.get(0);
                        int joinNum = groupGoodsBean.getJoinNum() == null ? 0 : groupGoodsBean.getJoinNum();
                        groupGoodsBean.setStock(groupGoodsBean.getStock() - c.getTotalNum());
                        groupGoodsBean.setSales(groupGoodsBean.getSales() + c.getTotalNum());
                        groupGoodsBean.setUpdateDate(new Date());
                        groupGoodsBean.setJoinNum(joinNum + 1);
                        String redisKey = String.format(Const.GROUP_GOODS_KEY, groupGoodsBean.getId());
                        if (redisService.hasKey(redisKey)) {
                            List<GroupRedisBean> groupRedisBeanList = (List<GroupRedisBean>) redisService.get(redisKey);
                            if (!CollectionUtils.isEmpty(groupRedisBeanList)) {
                                //小于成团数
                                if (groupRedisBeanList.size() < groupGoodsBean.getGroupNum() - 1) {
                                    groupRedisBeanList.add(new GroupRedisBean(userBean.getOpenId(), groupRedisBeanList.get(0).getGroupId()));
                                    orderService.updateGroupPayPrice(groupRedisBeanList.get(0).getGroupId(), 6, c.getTotalPrice(), c.getId());
                                    redisService.set(redisKey, groupRedisBeanList);
                                } else {//拼团成功
                                    int groupedNum = groupGoodsBean.getGroupedNum() == null ? 0 : groupGoodsBean.getGroupedNum();
                                    groupGoodsBean.setGroupedNum(groupedNum + 1);
                                    orderService.updateGroupPayPrice(groupRedisBeanList.get(0).getGroupId(), 6, c.getTotalPrice(), c.getId());
                                    redisService.del(redisKey);
                                    //开始统一更新状态
                                    orderService.updateStatusByGroupNum(2, groupRedisBeanList.get(0).getGroupId());
                                    List<GoodsAttrValueBean> goodsAttrValueBeanList = goodsAttrValueBeanMapper.selectByByGoodsIdAndSuk(groupGoodsBean.getId(), c.getGoodsAttr(), 2);
                                    if (!CollectionUtils.isEmpty(goodsAttrValueBeanList)) {
                                        GoodsAttrValueBean goodsAttrValueBean = goodsAttrValueBeanList.get(0);
                                        int spreadMoney = goodsAttrValueBean.getSpreadMoney() == null ? 0 : Integer.parseInt(goodsAttrValueBean.getSpreadMoney());
                                        int speadChildMoney = goodsAttrValueBean.getSpreadChildMoney() == null ? 0 : Integer.parseInt(goodsAttrValueBean.getSpreadChildMoney());
                                        totalSpreadMoney += spreadMoney;
                                        totalSpreadChildMoney += speadChildMoney;
                                        if (-1 != parentId) {
                                            shareParentMap.put(parentId, new ShareMoneyBean(totalSpreadMoney, totalSpreadChildMoney));
                                        }
                                    }
                                }
                            }
                        } else {
                            List<GroupRedisBean> groupRedisBeanList = new ArrayList<>();
                            groupRedisBeanList.add(new GroupRedisBean(userBean.getOpenId(), UUID.randomUUID().toString().replaceAll("-", "")));
                            redisService.set(redisKey, groupRedisBeanList);
                            orderService.updateGroupPayPrice(groupRedisBeanList.get(0).getGroupId(), 6, c.getTotalPrice(), c.getId());
                        }
                        groupGoodsBeanMapper.updateByPrimaryKey(groupGoodsBean);
                        merIdSet.add(0);
                    } else {
                        log.error("【拼团订单 {} 找不到商品】", c.getOrderId());
                    }
                }
            }
            //发送短信通知掌柜
            smsService.newOrderNofity(merIdSet, orderSeq, totalFee);
            //发短信通知合伙人
            List<SpreadInfoBean> childIds = spreadInfoBeanMapper.selectByChildId(userBean.getOpenId());
            if (totalSpreadMoney > 0) {
                if (userBean.getIsSpread() == 1) {
                    //合伙人自己购买一级返佣
                    smsService.partnerOrderNotify(userBean, orderSeq, BusinessUtil.getWebAmount(totalSpreadMoney));
                    SpreadMoneyBean spreadMoneyBean = new SpreadMoneyBean();
                    spreadMoneyBean.setCreateTime(new Date());
                    spreadMoneyBean.setOrderSeq(orderSeq);
                    spreadMoneyBean.setOpenId(userBean.getOpenId());
                    spreadMoneyBean.setIsAccount(0);
                    spreadMoneyBean.setSpreadMoney(totalSpreadMoney);
                    spreadMoneyBean.setToAccountTime(DateUtils.addDays(new Date(), 10));
                    spreadMoneyBean.setRemark("合伙人自己购买一级返佣");
                    spreadMoneyBeanMapper.insert(spreadMoneyBean);
                    shareParentMap.remove(userBean.getId());
                } else if (!CollectionUtils.isEmpty(childIds)) {
                    //下级购买 下级自己获得一级返佣
                    SpreadMoneyBean spreadMoneyBean = new SpreadMoneyBean();
                    spreadMoneyBean.setCreateTime(new Date());
                    spreadMoneyBean.setOrderSeq(orderSeq);
                    spreadMoneyBean.setOpenId(userBean.getOpenId());
                    spreadMoneyBean.setIsAccount(0);
                    spreadMoneyBean.setSpreadMoney(totalSpreadMoney);
                    spreadMoneyBean.setToAccountTime(DateUtils.addDays(new Date(), 10));
                    spreadMoneyBean.setRemark("下级购买下级获得一级返佣");
                    spreadMoneyBeanMapper.insert(spreadMoneyBean);
                    shareParentMap.remove(userBean.getId());
                }
            }
            if (totalSpreadChildMoney > 0) {
                if (!CollectionUtils.isEmpty(childIds)) {
                    //代理商下级自己购买计算佣金
                    SpreadInfoBean spreadInfoBean = childIds.get(0);
                    //给上级分二级佣金
                    UserBean parentBean = userBeanMapper.selectByOpenId(spreadInfoBean.getParentId());
                    smsService.partnerOrderNotify(parentBean, orderSeq, BusinessUtil.getWebAmount(totalSpreadChildMoney));
                    SpreadMoneyBean spreadMoneyBean = new SpreadMoneyBean();
                    spreadMoneyBean.setCreateTime(new Date());
                    spreadMoneyBean.setOrderSeq(orderSeq);
                    spreadMoneyBean.setOpenId(parentBean.getOpenId());
                    spreadMoneyBean.setIsAccount(0);
                    spreadMoneyBean.setSpreadMoney(totalSpreadChildMoney);
                    spreadMoneyBean.setToAccountTime(DateUtils.addDays(new Date(), 10));
                    spreadMoneyBean.setRemark("下级购买上级分二级佣金");
                    spreadMoneyBeanMapper.insert(spreadMoneyBean);
                    shareParentMap.remove(parentBean.getId());
                }
            }
            if (MapUtils.isNotEmpty(shareParentMap)) {
                for (Map.Entry<Integer, ShareMoneyBean> entry : shareParentMap.entrySet()) {
                    int userId = entry.getKey();
                    ShareMoneyBean shareMoneyBean = entry.getValue();
                    if (shareMoneyBean.getSpreadChildMoney() > 0 || shareMoneyBean.getSpreadMoney() > 0) {
                        UserBean parentBean = userBeanMapper.selectByPrimaryKey(userId);
                        if (null != parentBean) {
                            List<SpreadInfoBean> shareChildIds = spreadInfoBeanMapper.selectByChildId(parentBean.getOpenId());
                            if (shareMoneyBean.getSpreadMoney() > 0) {
                                //分享出去的 一级返佣
                                SpreadMoneyBean spreadMoneyBean = new SpreadMoneyBean();
                                spreadMoneyBean.setCreateTime(new Date());
                                spreadMoneyBean.setOrderSeq(orderSeq);
                                spreadMoneyBean.setOpenId(parentBean.getOpenId());
                                spreadMoneyBean.setIsAccount(0);
                                spreadMoneyBean.setSpreadMoney(shareMoneyBean.getSpreadMoney());
                                spreadMoneyBean.setToAccountTime(DateUtils.addDays(new Date(), 10));
                                spreadMoneyBean.setRemark("分享购买商品赠送一级佣金");
                                spreadMoneyBeanMapper.insert(spreadMoneyBean);
                            }

                            if (shareMoneyBean.getSpreadChildMoney() > 0 && !CollectionUtils.isEmpty(shareChildIds)) {
                                //合伙人上级分二级佣金
                                SpreadMoneyBean spreadChildMoneyBean = new SpreadMoneyBean();
                                spreadChildMoneyBean.setCreateTime(new Date());
                                spreadChildMoneyBean.setOrderSeq(orderSeq);
                                spreadChildMoneyBean.setOpenId(shareChildIds.get(0).getParentId());
                                spreadChildMoneyBean.setIsAccount(0);
                                spreadChildMoneyBean.setSpreadMoney(shareMoneyBean.getSpreadChildMoney());
                                spreadChildMoneyBean.setToAccountTime(DateUtils.addDays(new Date(), 10));
                                spreadChildMoneyBean.setRemark("下级分享购买商品赠送二级佣金");
                                spreadMoneyBeanMapper.insert(spreadChildMoneyBean);
                            }
                        }
                    }
                }
            }


            if (givingScore > 0) {
                userBean.setScore(userBean.getScore() + givingScore);
                ScoreSeqBean scoreSeqBean = new ScoreSeqBean();
                scoreSeqBean.setCreateDate(new Date());
                scoreSeqBean.setOpenId(userBean.getOpenId());
                scoreSeqBean.setRemark("购买商品赠送积分");
                scoreSeqBean.setScore(givingScore);
                scoreSeqBean.setType(1);
                scoreSeqBean.setOrderSeq(orderSeq);
                scoreSeqBeanMapper.insert(scoreSeqBean);
                userBeanMapper.updateByPrimaryKeySelective(userBean);
                redisService.del(String.format(Const.USER_REDIS_KEY, userBean.getOpenId()));
            }
            if (userScore > 0) {
                ScoreSeqBean scoreSeqBean = new ScoreSeqBean();
                scoreSeqBean.setType(2);
                scoreSeqBean.setScore(userScore);
                scoreSeqBean.setRemark("购买商品使用积分");
                scoreSeqBean.setCreateDate(new Date());
                scoreSeqBean.setOpenId(userBean.getOpenId());
                scoreSeqBean.setOrderSeq(orderSeq);
                scoreSeqBeanMapper.insert(scoreSeqBean);
                userBean.setScore(userBean.getScore() - userScore);
                userBean.setUpdateDate(new Date());
                userBeanMapper.updateByPrimaryKeySelective(userBean);
                redisService.del(String.format(Const.USER_REDIS_KEY, userBean.getOpenId()));
            }
            if (userMoney > 0) {
                AcctbkSeqBean acctbkSeqBean = new AcctbkSeqBean();
                acctbkSeqBean.setType(2);
                acctbkSeqBean.setMoney(String.valueOf(userMoney));
                acctbkSeqBean.setRemark("购买商品使用余额");
                acctbkSeqBean.setCreateDate(new Date());
                acctbkSeqBean.setOpenId(userBean.getOpenId());
                acctbkSeqBeanMapper.insert(acctbkSeqBean);
                userBean.setMoney(userBean.getMoney() - userMoney);
                userBean.setUpdateDate(new Date());
                userBeanMapper.updateByPrimaryKeySelective(userBean);
                redisService.del(String.format(Const.USER_REDIS_KEY, userBean.getOpenId()));
            }
            if (null != userCoupons) {
                //优惠卷使用
                CouponsSeqBean couponsSeqBean = new CouponsSeqBean();
                couponsSeqBean.setCreateTime(new Date());
                couponsSeqBean.setType(2);
                couponsSeqBean.setUserId(userBean.getId());
                couponsSeqBean.setCouponsId(userCoupons);
                couponsSeqBean.setOrderSeq(orderSeq);
                couponsSeqBeanMapper.insert(couponsSeqBean);
            }
            if (totalPayPrice[0] != Integer.parseInt(result.getTotal_fee())) {
                log.error("【支付回调  orderSeq={} 应支付金额 {} 和 实际支付金额 {} 不一致,请开发注意】", orderSeq, totalPayPrice[0], result.getTotal_fee());
            }
        } else {
            List<ApplyInfoBean> applyInfoBeanList = applyInfoService.selectByPaySeq(orderSeq);
            if (CollectionUtils.isEmpty(applyInfoBeanList)) {
                throw new BusinessException(500, "订单号：" + orderSeq + "不正确");
            }
            for (ApplyInfoBean c : applyInfoBeanList) {
                applyInfoService.updatePayStatus(1, Integer.parseInt(result.getTotal_fee()), c.getPaySeq());
                if ("2".equals(orderType)) {
                    userBean.setIsVip(1);
                    userBean.setUpdateDate(new Date());
                    userBeanMapper.updateByPrimaryKeySelective(userBean);
                    redisService.del(String.format(Const.USER_REDIS_KEY, userBean.getOpenId()));
                } else if ("3".equals(orderType)) {
                    String miniUrl = qrCodeUtil.createQrCode(Const.CLIENT_MINI, userBean.getId());
                    String h5Url = qrCodeUtil.createQrCode(Const.CLIENT_H5, userBean.getId());
                    userBean.setSignDate(new Date());
                    userBean.setUserSign(miniUrl + "," + h5Url);
                    userBean.setIsVip(1);
                    userBean.setIsSpread(1);
                    userBean.setUpdateDate(new Date());
                    userBeanMapper.updateByPrimaryKeySelective(userBean);
                    redisService.del(String.format(Const.USER_REDIS_KEY, userBean.getOpenId()));
                }
            }
        }

        if (totalFee > 0 && userScore > 0) {
            //微信 积分 组合支付
            orderService.updatePayTypeByOrderSeq(orderSeq, 3);
        } else if (totalFee > 0 && userScore <= 0) {
            //微信支付
            orderService.updatePayTypeByOrderSeq(orderSeq, 1);
        } else if (totalFee <= 0 && userScore > 0) {
            //积分支付
            orderService.updatePayTypeByOrderSeq(orderSeq, 2);
        }
        if (totalFee <= 0) {
            return;
        }
        //最后插入微信流水
        WeiXinNotifyBean weiXinNodifyBean = new WeiXinNotifyBean();
        weiXinNodifyBean.setAttach(attach);
        weiXinNodifyBean.setBankType(result.getBank_type());
        weiXinNodifyBean.setCreateDate(new Date());
        weiXinNodifyBean.setOrderSeq(orderSeq);
        weiXinNodifyBean.setTotalFee(Integer.parseInt(result.getTotal_fee()));
        weiXinNodifyBean.setOpenId(userBean.getOpenId());
        weiXinNodifyBean.setRemark("支付回调");
        weiXinNodifyBean.setCreateDate(new Date());
        weiXinNotifyBeanMapper.insert(weiXinNodifyBean);
    }

    /**
     * 退款接口
     *
     * @param refundParam
     * @return
     */
    public void refund(RefundParam refundParam) {
        List<WeiXinNotifyBean> weiXinNotifyBeanList = weiXinNotifyBeanMapper.selectByOrderSeq(refundParam.getOrderSeq());
        if (org.apache.commons.collections.CollectionUtils.isEmpty(weiXinNotifyBeanList)) {
            throw new BusinessException("订单编号不存在");
        }
        WeiXinNotifyBean weiXinNotifyBean = weiXinNotifyBeanList.get(0);
        if (refundParam.getRefundFee() > weiXinNotifyBean.getTotalFee()) {
            throw new BusinessException("退款金额不能大于付款金额");
        }
        SortedMap<String, Object> map = new TreeMap<>();
        map.put("appid", weiXinConfig.getAppId());
        map.put("mch_id", weiXinConfig.getMchId());
        map.put("nonce_str", WeChatUtils.getRandomStr(32));
        map.put("out_trade_no", refundParam.getOrderSeq());
        map.put("out_refund_no", BusinessUtil.getOrderSeq(0));
        map.put("total_fee", weiXinNotifyBean.getTotalFee());
        map.put("refund_fee", refundParam.getRefundFee());
        map.put("refund_desc", refundParam.getRefundDesc());

        Map<String, String> resultMap = new HashMap<>();
        try {
            // 调用工具类，将Map集合转化为带签名sign的XML格式字符串
            String sign = WeChatUtils.createSign(map, weiXinConfig.getPaySignKey());
            map.put("sign", sign);
            String resultXml = ClientCustomSSL.doRefund(weiXinConfig, WeChatUtils.sendMapToXml(map));
            resultMap = WeChatUtils.xmlToMap(resultXml);
        } catch (Exception e) {
            log.error("调用退款接口失败", e);
            throw new BusinessException(resultMap.get("调用退款接口失败"));
        }
        // 微信端返回字符串为成功时，退款成功,更新数据
        if (resultMap.get("return_code").equals("SUCCESS") && resultMap.get("result_code").equals("SUCCESS")) {
            // 退款成功时，在此处更改订单的状态，并更新数据库对应信息
            log.info("退款成功");
            for (WeiXinNotifyBean bean : weiXinNotifyBeanList) {
                weiXinNotifyBeanMapper.deleteByPrimaryKey(bean.getId());
            }
        } else {
            throw new BusinessException(resultMap.get("err_code_des"));
        }
    }

    private JSONObject getOrderInfoByOrderSeq(String orderSeq) throws BusinessException {
        String orderType = orderSeq.substring(orderSeq.length() - 1, orderSeq.length());
        JSONObject jsonObject = new JSONObject();
        if ("1".equals(orderType)) {
            List<OrderBean> list = orderService.selectByOrderId(orderSeq);
            if (CollectionUtils.isEmpty(list)) {
                throw new BusinessException(500, "订单号：" + orderSeq + "不正确");
            }
            jsonObject.put("attach", "好沐友商品消费");
            final int[] totalPrice = {0};
            final int[] orderMinType = {0};
            list.stream().forEach(c -> {
                totalPrice[0] += c.getTotalPrice();
                orderMinType[0] = c.getOrderType();
            });
            Integer useScore = list.get(0).getUserScore();
            Integer userMoney = list.get(0).getUserMoney();
            Integer userCoupons = list.get(0).getUserCoupons();
            useScore = null == useScore ? 0 : useScore;
            userMoney = null == userMoney ? 0 : userMoney;
            if (null != userCoupons && 0 != userCoupons) {
                CouponsBean couponsBean = couponsBeanMapper.selectByPrimaryKey(userCoupons);
                if (null != couponsBean) {
                    if (totalPrice[0] >= BusinessUtil.getDbAmount(couponsBean.getMinAmount())) {
                        totalPrice[0] -= BusinessUtil.getDbAmount(couponsBean.getDiscountAmount());
                    }
                }
            }
            jsonObject.put("body", "好沐友商品消费");
            if (orderMinType[0] == 4) {
                jsonObject.put("totalFee", totalPrice[0] - userMoney);
            } else {
                jsonObject.put("totalFee", totalPrice[0] - useScore * 5 - userMoney);
            }
        } else {
            List<ApplyInfoBean> applyInfoBeanList = applyInfoService.selectByPaySeq(orderSeq);
            if (CollectionUtils.isEmpty(applyInfoBeanList)) {
                throw new BusinessException(500, "订单号：" + orderSeq + "不正确");
            }
            String body = null;
            String attach = null;
            int totalFee = 0;
            if ("2".equals(orderType)) {
                body = "好沐友VIP申请消费";
                attach = "好沐友VIP申请消费";
                totalFee = weiXinConfig.getVipPrice();
            } else if ("3".equals(orderType)) {
                body = "好沐友合伙人申请消费";
                attach = "好沐友合伙人申请消费";
                totalFee = weiXinConfig.getSpreadPrice();
            }
            jsonObject.put("attach", attach);
            jsonObject.put("body", body);
            jsonObject.put("totalFee", totalFee);
        }
        int payFee = jsonObject.getInteger("totalFee");
        if (payFee <= 0) {
            throw new BusinessException(500, "支付金额不正确：" + BusinessUtil.getWebAmount(payFee));
        }
        return jsonObject;
    }

    /**
     * 构建统一下单参数map 用于生成签名
     *
     * @param data
     * @return SortedMap<String,Object>
     */
    private SortedMap<String, Object> buildParamMap(WxPaySendData data) {
        SortedMap<String, Object> paramters = new TreeMap<String, Object>();
        if (null != data) {
            if (StringUtils.isNotEmpty(data.getAppId())) {
                paramters.put("appid", data.getAppId());
            }
            if (StringUtils.isNotEmpty(data.getAttach())) {
                paramters.put("attach", data.getAttach());
            }
            if (StringUtils.isNotEmpty(data.getBody())) {
                paramters.put("body", data.getBody());
            }
            if (StringUtils.isNotEmpty(data.getDetail())) {
                paramters.put("detail", data.getDetail());
            }
            if (StringUtils.isNotEmpty(data.getDeviceInfo())) {
                paramters.put("device_info", data.getDeviceInfo());
            }
            if (StringUtils.isNotEmpty(data.getFeeType())) {
                paramters.put("fee_type", data.getFeeType());
            }
            if (StringUtils.isNotEmpty(data.getGoodsTag())) {
                paramters.put("goods_tag", data.getGoodsTag());
            }
            if (StringUtils.isNotEmpty(data.getLimitPay())) {
                paramters.put("limit_pay", data.getLimitPay());
            }
            if (StringUtils.isNotEmpty(data.getMchId())) {
                paramters.put("mch_id", data.getMchId());
            }
            if (StringUtils.isNotEmpty(data.getNonceStr())) {
                paramters.put("nonce_str", data.getNonceStr());
            }
            if (StringUtils.isNotEmpty(data.getNotifyUrl())) {
                paramters.put("notify_url", data.getNotifyUrl());
            }
            if (StringUtils.isNotEmpty(data.getOpenId())) {
                paramters.put("openid", data.getOpenId());
            }
            if (StringUtils.isNotEmpty(data.getOutTradeNo())) {
                paramters.put("out_trade_no", data.getOutTradeNo());
            }
            if (StringUtils.isNotEmpty(data.getSign())) {
                paramters.put("sign", data.getSign());
            }
            if (StringUtils.isNotEmpty(data.getSpBillCreateIp())) {
                paramters.put("spbill_create_ip", data.getSpBillCreateIp());
            }
            if (StringUtils.isNotEmpty(data.getTimeStart())) {
                paramters.put("time_start", data.getTimeStart());
            }
            if (StringUtils.isNotEmpty(data.getTimeExpire())) {
                paramters.put("time_expire", data.getTimeExpire());
            }
            if (StringUtils.isNotEmpty(data.getProductId())) {
                paramters.put("product_id", data.getProductId());
            }
            if (Integer.parseInt(data.getTotalFee()) > 0) {
                paramters.put("total_fee", data.getTotalFee());
            }
            if (StringUtils.isNotEmpty(data.getTradeType())) {
                paramters.put("trade_type", data.getTradeType());
            }
            //申请退款参数
            if (StringUtils.isNotEmpty(data.getTransactionId())) {
                paramters.put("transaction_id", data.getTransactionId());
            }
            if (StringUtils.isNotEmpty(data.getOutRefundNo())) {
                paramters.put("out_refund_no", data.getOutRefundNo());
            }
            if (StringUtils.isNotEmpty(data.getOpUserId())) {
                paramters.put("op_user_id", data.getOpUserId());
            }
            if (StringUtils.isNotEmpty(data.getRefundFeeType())) {
                paramters.put("refund_fee_type", data.getRefundFeeType());
            }
            if (null != data.getRefundFee() && data.getRefundFee() > 0) {
                paramters.put("refund_fee", data.getRefundFee());
            }
        }
        return paramters;
    }
}
